package com.lzc.springPart;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.MethodParameter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AutoWiredImpl{
    public static void main(String[] args) throws Throwable {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        // 实例化bean1
        Bean1 bean1 = new Bean1();

        // 创建Autowired后置处理器
        AutowiredAnnotationBeanPostProcessor postProcessor = new AutowiredAnnotationBeanPostProcessor();
        postProcessor.setBeanFactory(beanFactory);

        //postProcessor.postProcessProperties(null,bean1,"bean1");
        // 执行findAutowiringMetadata方法
        Method findAutowiringMetadata = postProcessor.getClass().getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata injectionMetadata =
                (InjectionMetadata) findAutowiringMetadata.invoke(postProcessor, "bean1", bean1.getClass(), null);

        injectionMetadata.inject(bean1,"bean1",null);
        // inject 执行流程
        /*Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(new MethodParameter(setBean2, 0),false);
        Bean2 o = (Bean2) beanFactory.doResolveDependency(dependencyDescriptor, null, null, null);
        setBean2.invoke(bean1,o);*/


    }

    static class Bean1{

        private Bean2 bean2;
        @Autowired
        public void setBean2(Bean2 bean2){
            this.bean2 = bean2;
            System.out.println("bean1 autowire =>>>>>>>" + bean2);
        }

    }

    static class Bean2{

    }
}
